import * as qs from 'qs';
import * as crypto from 'crypto';
import * as cryptoJS from 'crypto-js'
import { default as axios } from 'axios';
import { v4 as uuidv4 } from 'uuid';


const config = {
  /* openapi host */
  host: 'https://openapi.tuyacn.com',
  /* fetch from openapi platform */
  accessKey: "n8***********",
  /* fetch from openapi platform */
  secretKey: "1*********78",
  code:"89**********8"
};

const httpClient = axios.create({
  baseURL: config.host,
  timeout: 5 * 1e3,
});

/**
 * fetch highway login token
 */
async function getToken() {
  const method = 'GET';
  const timestamp  = new Date().getTime().toString();
  const signUrl = `/v1.0/authorize_token?code=${config.code}&grant_type=3`;
  const contentHash = crypto.createHash('sha256').update('').digest('hex');
  const stringToSign = [method, contentHash, "", signUrl].join("\n");
  const nonce  = "";
  const signStr = config.accessKey + timestamp + nonce + stringToSign;
  console.log(signStr)

  const headers = {
    client_id: config.accessKey,
    sign: await encryptStr(signStr, config.secretKey),
    t: timestamp,
    sign_method: 'HMAC-SHA256'
  };
  console.log(headers)
  const { data: login } = await httpClient.get(signUrl, { headers });
  if (!login || !login.success) {
    throw Error(`fetch failed: ${JSON.stringify(login)}`);
  }
  return login.result.access_token;
}

/**
 * fetch highway business data
 */
async function getDeviceInfo(deviceId) {
  const query = {};
  const method = 'POST';
  const url = `/v1.0/devices/${deviceId}/commands`;
  const reqHeaders = await getRequestSign(url, method, {}, query);

  const { data } = await httpClient.request({
    method,
    data: {},
    params: {},
    headers: reqHeaders,
    url: reqHeaders.path,
  });
  if (!data || !data.success) {
    throw Error(`request api failed: ${data.msg}`);
  }
}

/**
 * HMAC-SHA256 crypto function
 */
async function encryptStr(str, secret) {
  console.log(str);
  console.log(secret);
  //return String(cryptoJS.HmacSHA256(str, secret));
  return crypto.createHmac('sha256', secret).update(str, 'utf8').digest('hex').toUpperCase();
}

/**
 * request sign, save headers 
 * @param path
 * @param method
 * @param headers
 * @param query
 * @param body
 */
async function getRequestSign(
  path,
  method,
  headers = {},
  query = {},
  body = {},
) {
  const t = Date.now().toString();
  const [uri, pathQuery] = path.split('?');
  const queryMerged = Object.assign(query, qs.parse(pathQuery));
  const sortedQuery = {};
  Object.keys(queryMerged)
    .sort()
    .forEach((i) => (sortedQuery[i] = query[i]));

  const querystring = decodeURIComponent(qs.stringify(sortedQuery));
  const url = querystring ? `${uri}?${querystring}` : uri;
  const contentHash = crypto.createHash('sha256').update(JSON.stringify(body)).digest('hex');
  const stringToSign = [method, contentHash, '', url].join('\n');
  const token = await getToken();
  const signStr = config.accessKey + token + t + stringToSign;
  return {
    t,
    path: url,
    client_id: config.accessKey,
    sign: await encryptStr(signStr, config.secretKey),
    sign_method: 'HMAC-SHA256',
    access_token: token,
  };
}

export default {
  getToken,
  getDeviceInfo
}

